//
//  NetTools.swift
//  02-封装AFN
//
//  Created by 牛威 on 15/12/7.
//  Copyright © 2015年 牛威. All rights reserved.
//

import UIKit

import AFNetworking

//定义枚举

enum NWRequestMethod : String{

    case GET = "GET"
    
    case POST = "POST"


}

//MARK: - oauth应用拼接信息


private let appKey = "1081648050"
private let appSecret = "7b90de06f71695350f27473f41cf0744"
private let rediecturl = "http://www.baidu.com"

//MARK: - 单例的创建
class NetTools: AFHTTPSessionManager {
    
    
    static let shared : NetTools = {
    
       let tools = NetTools(baseURL: nil)
        
        tools.responseSerializer.acceptableContentTypes?.insert("text/plain")
//        tools.responseSerializer.acceptableContentTypes?.insert("text/html")
        
        return tools

    
    }()
   

}


//MARK: - 加载微博数据相关方法

extension NetTools {
    
    

    /// - see: [http://open.weibo.com/wiki/2/statuses/home_timeline](http://open.weibo.com/wiki/2/statuses/home_timeline)
    /// parameter since_id 若指定此参数，则返回ID比since_id大的微博（即比since_id时间晚的微博），默认为0。
    /// parameter max_id   若指定此参数，则返回ID小于或等于max_id的微博，默认为0。

    /// - parameter finshed: 回调
    ///这里写两个参数 第一个参数是外部参数 方便调用
    func loadStatus(since_id since_id : Int,max_id : Int,finshed:NWRequestCallback){
    
        
        var paras = [String : AnyObject]()
        
        if since_id > 0{ //下拉刷新
        
          paras["since_id"] = since_id
        
        }else if max_id > 0 { //上拉刷新
        
          paras["max_id"] = max_id - 1 //解决重复微博问题 ---->则返回ID小于或等于max_id的微博，
        
        }
        
        

       let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
        
        tokenRequest(.GET, urlString: urlString, parameters: paras, finshed: finshed)
    
    }



}


//MARK: - 发送微博的相关方法

extension NetTools {
    
    /// 发送微博的方法
    ///  - see: [http://open.weibo.com/wiki/2/statuses/update](http://open.weibo.com/wiki/2/statuses/update)
    /// - see: [http://open.weibo.com/wiki/2/statuses/upload](http://open.weibo.com/wiki/2/statuses/upload)
    /// - parameter image   发送微博配图
    /// - parameter status:  string	要发布的微博文本内容，必须做URLencode，内容不超过140个汉字。
    /// - parameter finshed: 完成后的回调

    func sendWBMethod(status:String,image :UIImage?, finshed:NWRequestCallback){
    
        //实例化token字典
        
        var paras = [String : AnyObject]()

        
        paras["status"] = status
        
        if image == nil {
        
            let urlString = "https://api.weibo.com/2/statuses/update.json"
            
            tokenRequest(.POST, urlString: urlString, parameters: paras, finshed: finshed)
            
        
        }else{
        
           let urlString = "https://upload.api.weibo.com/2/statuses/upload.json"
        
            let data = UIImagePNGRepresentation(image!)
            
            uploadFile(urlString, data: data!, name: "pic", parameters: paras, finshed: finshed)
        }
        
    
    }
}



//MARK: - 访问用户信息
extension NetTools {

    //   url: https://api.weibo.com/2/users/show.json access_token uid
    ///  - see: [http://open.weibo.com/wiki/2/users/show](http://open.weibo.com/wiki/2/users/show)
    ///
    /// - parameter uid:     需要查询的用户id
    /// - parameter finshed: 回调
    func loadUserInfo(Uid uid:String,finshed:NWRequestCallback){
    
        
        //实例化token字典
        
        var paras = [String : AnyObject]()

        
        paras["uid"] = uid
     
        let urlString = "https://api.weibo.com/2/users/show.json"
        
    
        tokenRequest(.GET, urlString: urlString, parameters: paras, finshed: finshed)
    
    
    }


}




//拼接oauth连接

extension NetTools {
    
    //

   /// - see: [wwww.baidu.com](wwww.baidu.com)
    var oauthURL:NSURL  {
        
        
    //https://api.weibo.com/oauth2/authorize?
    
let urlString = "https://api.weibo.com/oauth2/authorize?client_id=\(appKey)&redirect_uri=\(rediecturl)"
        
        return NSURL(string: urlString)!
    
    
    }
    
    
    //MARK: - 加载accessToken
    
    //swift中的起别名  typealias 定义的别名首字母有要大写 其他不需要注意
    
    typealias NWRequestCallback = (result:AnyObject?,error:NSError?)->()
    
    
    
    
    func loadAccessToken(code:String,finshed:NWRequestCallback){
        
        
        //https://api.weibo.com/oauth2/access_token

 
        let urlString = "https://api.weibo.com/oauth2/access_token"
    
    
      let paras = [ "client_id":appKey,
                    "client_secret":appSecret,
                    "grant_type":"authorization_code",
                    "code":code,
                    "redirect_uri":rediecturl]
        
        
        request(.POST, urlString: urlString, parameters: paras, finshed: finshed)
        
    }
}




//MARK: - 封装网络工具 集成这中网络框架的时候方法应该受保护 是私有的所以加上private


extension NetTools {
    
    
    
    //MARK: - 抽取token封装网络方法
    
    private func tokenRequest(method:NWRequestMethod, urlString:String,var parameters:[String : AnyObject]?,finshed:NWRequestCallback){
        
        
        //使用追加token
        
        if !addToken(&parameters) {
            
            finshed(result: nil, error: NSError(domain: "cn.baidu.com", code: 0126, userInfo: ["message":"token is nil"]))
            
            return
            
            
        }

           //2调用网络方法
        
          request(method, urlString: urlString, parameters: parameters, finshed: finshed)
    
    }


  private  func request(method:NWRequestMethod, urlString:String,parameters:[String : AnyObject]?,finshed:NWRequestCallback){
        
        let success = {(task :NSURLSessionDataTask, result:AnyObject) -> Void in
        
            finshed(result: result, error: nil)

        
        }
        
        let failure = {(task:NSURLSessionDataTask?,error: NSError) -> Void in
        
            finshed(result: nil, error: error)

        
        }
        
        
        
        if method == NWRequestMethod.GET {
        
          GET(urlString, parameters: parameters, success: success, failure: failure)
            
        
        
        }else {
        
          POST(urlString, parameters: parameters, success: success, failure: failure)
        
        }
    
    }
    
    
    //MARK: - 往参数字典中追加token值
    
    private func addToken(inout parameters:[String : AnyObject]?)->Bool{
        
        guard let token = UserAccountViewModel.sharedAccount.accessToken else{
            
            
            return false
        }
    
        if parameters == nil {
            
            
            parameters = [String : AnyObject]()
            
        }

         parameters!["access_token"] = token
        
        return true
    
    }
    
    
    
    //MARK: - 使用AFN上传文件的方法
    
    private func uploadFile(urlString:String,data:NSData,name:String,var parameters:[String : AnyObject]?,finshed:NWRequestCallback){
        
        
        
        //使用追加token
        
        if !addToken(&parameters) {
        
            finshed(result: nil, error: NSError(domain: "cn.baidu.com", code: 0126, userInfo: ["message":"token is nil"]))
            
            return

        
        }
        
        //使用AFN上传图片
        

        //formData没有只能提示 所以在这定义一个
        
//        var formData : AFMultipartFormData = AFMultipartFormData()
        
        /// AFMultipartFormData 协议的一个方法
        ///
        /// @param data       要上传的文件的二进制数据
        /// @param name       服务器定义的字段名称,后台接口文档会提示
        /// @param fileName   保存在服务器的文件名,但是现在通常可以乱写,后台会做后续处理
        ///                   根据上传的文件 生成缩略图 中等图 高清图
        ///                   保存在不同路径,生成不同的名称 都没用还要写干嘛!!-->fileName是HTTP协议定义的属性
        ///
        /// @param mimeType /contentType 客户端告诉服务器,二进制文件准确的类型 格式'大类型/小类型' 无需记忆
        
    
    
      POST(urlString, parameters: parameters, constructingBodyWithBlock: { (formData) -> Void in
        
        
        formData.appendPartWithFileData(data,name: name,fileName: "xxx",mimeType: "application/octet-stream")

        
        }, success: { (_, result) -> Void in
            
            finshed(result: result, error: nil)

            
        }) { (_, error) -> Void in
            
            print(error)
            
            finshed(result: nil, error: error)

        }
    
    
    }
}
